#include "UDPServer.hpp"
#include "User.hpp"
using namespace server;
using namespace user;

//todo demo1: 英翻中
// const char* dictionary_file = "dictionary.txt";
// unordered_map<string, string> dic;
// namespace translate {
//     // 字符串分割，将中英文分开存入到字典中
//     static bool cutString(const string& target, string* s1, string* s2, const string& separator) {
//         size_t pos = target.find(separator); // 找到分隔符所在的下标
//         if (pos == string::npos) return false; // 没找到
//         *s1 = target.substr(0, pos);
//         *s2 = target.substr(pos + separator.size()); // pos + separator.size()是为了避免多个分割符的情况，如apple:::::苹果
//         return true;
//     }

//     // static修饰函数，让该函数只能在该文件内被看到，其他文件都用不了
//     static void initDictionary() {
//         ifstream ifs(dictionary_file, ios_base::in);
//         if (!ifs.is_open()) {
//             cerr << "open file " << dictionary_file << " fail" << endl;
//             exit(OPEN_ERR);
//         }

//         string line;
//         string key, value;
//         while(getline(ifs, line)) {
//             if (cutString(line, &key, &value, ":")) {
//                 dic.insert(make_pair(key,value));
//             }
//         }

//         ifs.close();
//         cout << "load dictionary success!" << endl;
//     }

//     // 捕捉某一个信号来完成字典的重新加载
//     // 这样可以做到通过信号在程序的运行过程中来完成字典的热加载，而不需要终止任务来重新加载
//     // 类似游戏的不停机更新
//     void reload(int) {
//         initDictionary();
//     }

//     void handleMessage(int sockfd, string client_ip, uint16_t client_port, string message) {
//         // 可以自行定义对message的处理方法而不关系message是如何来的，做到网络通信与业务逻辑的解耦

//         // 查询意思
//         string response;
//         unordered_map<string, string>::iterator ite = dic.find(message);
//         if (ite == dic.end()) response = "unknow";
//         else response = ite->second;

//         // 返回给客户端
//         struct sockaddr_in client;
//         bzero(&client, sizeof client);
//         client.sin_family = AF_INET;
//         client.sin_port = htons(client_port);
//         client.sin_addr.s_addr = inet_addr(client_ip.c_str());

//         sendto(sockfd, response.c_str(), response.size(), 0, (struct sockaddr*)&client, sizeof(client));
//     }
// }

//todo demo2: 原理版XShell(远程服务器)
// namespace easy_xshell {
//     void execCommand(int sockfd, string client_ip, uint16_t client_port, string cmd) {
//         // 防止群众中有坏人
//         if (cmd.find("rm") != string::npos || cmd.find("rmdir") != string::npos || cmd.find("mv") != string::npos) {
//             cerr << client_ip << " : " << client_port << " 正在做一个非法操作 " << cmd << endl;
//             return;
//         }

//         string response;
//         //* popen = pipe + fork + exec, 创建一个子进程，用进程替换让子进程来执行cmd命令，并用管道返回结果(或输入参数)
//         FILE* fp = popen(cmd.c_str(), "r"); // 将cmd命令替换给子进程执行，并用读方式打开管道，从中读取数据
//         if (fp == nullptr) response = cmd + "exec failed!";

//         char line_buffer[1024];
//         bzero(line_buffer, sizeof(line_buffer));

//         // 如果fgets没获取到消息会返回nullptr
//         while (fgets(line_buffer, sizeof(line_buffer), fp)) { // 从fp中获取通过管道返回的消息
//             response += line_buffer;
//         }
//         pclose(fp);

//         // 返回结果
//         struct sockaddr_in client;
//         bzero(&client, sizeof(client));
//         client.sin_family = AF_INET;
//         client.sin_port = htons(client_port);
//         client.sin_addr.s_addr = inet_addr(client_ip.c_str());

//         sendto(sockfd, response.c_str(), response.size(), 0, (struct sockaddr*)&client, sizeof(client));
//     }
// }

//todo demo3: 聊天室
OnlineUser online_user;
namespace chatroom {
    void routeMessage(int sockfd, string client_ip, uint16_t client_port, string message) {
        if (message == "online") online_user.addUser(client_ip, client_port);
        if (message == "offline") online_user.removeUser(client_ip, client_port);

        if(online_user.isOnline(client_ip, client_port)) {
            // 如果用户上线了，就在在线用户大厅里广播
            online_user.broadcastMessage(sockfd, client_ip, client_port, message);
        }
        else {
            struct sockaddr_in client;
            bzero(&client, sizeof(client));

            client.sin_family = AF_INET;
            client.sin_port = htons(client_port);
            client.sin_addr.s_addr = inet_addr(client_ip.c_str());

            string response("你还没有上线，请先运行“online”上线！");
            sendto(sockfd, response.c_str(), response.size(), 0, (struct sockaddr*)&client, sizeof(client));
        }
    }
}


// ./UDPServer port
int main(int argc, char** argv) {
    if (argc != 2) {
        UDPServer::usage(argv[0]);
        exit(USAGE_ERR);
    }

    uint16_t port = static_cast<uint16_t>(atoi(argv[1]));

    // unique_ptr<UDPServer> udp_server(new UDPServer(translate::handleMessage, port));
    // translate::initDictionary();
    // signal(3, translate::reload);

    // unique_ptr<UDPServer> udp_server(new UDPServer(easy_xshell::execCommand, port));
    unique_ptr<UDPServer> udp_server(new UDPServer(chatroom::routeMessage, port));

    udp_server->initServer();
    udp_server->start();

    return 0;
} //@end main